/**
 * 教师批改插件说明
 * 
 * 依赖jq包
 * 需要引入canvas.css
 * 要求将被渲染为批改层的div的id名为painter
 * 调用方式为:
 * $('#painter').setCanvas({
 *      question: '背景图片地址',
 *      savePoint: [回显x坐标, 回显y坐标],//用不上了，但是暂时保留，不传该参数无影响
        dragArr: [] //回显提交的数据,用不上了，但是暂时保留，不传该参数无影响
 * });
 */
(function($) {
    function Painter(options) {
        this.wrapper = options.wrapper;
        this.bgUrl = options.question;
        this.getBase64 = options.getBase64; //通过回调函数获取生成的base64 add by chh
        this.bgImage = null;
        this.dragArr = options.dragArr || [];
        this.bgCan = null;
        this.panCan = null;
        this.panType = 'p0';
        this.history = null;
        this.x1 = 0;
        this.y1 = 0;
        this.dragX = options.savePoint ? -options.savePoint[0] : 0;
        this.dragY = options.savePoint ? -options.savePoint[1] : 0;
        this.saveX = 0;
        this.saveY = 0;
        this.scale = 1;
        this.rotateCount = 0;
        this.rotateRange = 0;
        this.drawingSurfaceImageData = null;
        this.init();
    }

    Painter.prototype.init = function() {
        this.createCan();
    }

    Painter.prototype.createCan = function() { /* 创建canvas相关html元素 */
        var canContent = '<div id="painterBar">\
                    <span class="painterBrush painter-active"></span>\
                    <span class="painterErase"></span>\
                    <span class="painterHook"></span>\
                    <span class="painterFork"></span>\
                    <span class="painterCircle"></span>\
                    <span class="painterBlock"></span>\
                    <span class="painterShowText"></span>\
                    <span class="painterBack"></span>\
                    <span class="painterClear"></span>\
                    <span class="painterDrag"></span>\
                    <span class="painterScaleBig"></span>\
                    <span class="painterScaleSmall"></span>\
                    <span class="painterRotate"></span>\
                    <span class="painterSave">保存</span>\
                    </div>\
                    <input id="painterText" class="form-control">\
                    <div id="painterCan">\
                    <canvas id="c2" style="display:none;"></canvas>\
                    <canvas id="c0"></canvas>\
                    <canvas id="c1"></canvas>\
                    </div>';
        $(this.wrapper).html(canContent);
        /* 动态设置canvas样式，防止图片变形 */
        $('#c0').attr('width', $('#painterCan').width());
        $('#c0').attr('height', $('#painterCan').height());
        $('#c1').attr('width', $('#painterCan').width());
        $('#c1').attr('height', $('#painterCan').height());
        this.rander();
        this.bindEvent();
        if (this.dragArr.length > 0) {
            this.echo(this.panCan, this.dragArr);
            this.dragX = 0;
            this.dragY = 0;
        }
    }

    Painter.prototype.rander = function() { /* 渲染canvas，bgCan为背景图片，panCan为教师绘制层 */
        this.bgCan = $('#c0')[0].getContext('2d');
        this.panCan = $('#c1')[0].getContext('2d');
        var that = this;
        that.bgImage = new Image();
        that.bgImage.setAttribute('crossOrigin', 'Anonymous')
        that.bgImage.src = this.bgUrl;
        that.bgImage.onload = function() {

            $('#c2').attr('width', that.bgImage.width);
            $('#c2').attr('height', that.bgImage.height);
            that.rotateRange = that.bgImage.width > that.bgImage.height ? that.bgImage.width : that.bgImage.height;
            that.bgCan.drawImage(that.bgImage, 0, 0);
        }
    }

    Painter.prototype.bindEvent = function() { /* 绑定事件 */
        var that = this;
        $('#painterBar span').click(function() {
            $(this).addClass('painter-active').siblings().removeClass('painter-active');
        })
        $('#painterCan').bind('resize', function() { /* 监听窗口大小改变事件 */
            $('#c0').attr('width', $('#painterCan').width());
            $('#c0').attr('height', $('#painterCan').height());
            $('#c1').attr('width', $('#painterCan').width());
            $('#c1').attr('height', $('#painterCan').height());
            that.rander();
            if (that.dragArr.length > 0) {
                that.echo(that.panCan, that.dragArr);
            }
        });
        /* 工具栏点击切换画笔功能 */
        $('.painterBrush').click(function() {
            that.panType = 'p0';
        })
        $('.painterErase').click(function() {
            that.panType = 'p1';
        })
        $('.painterHook').click(function() {
            that.panType = 'p2';
        })
        $('.painterFork').click(function() {
            that.panType = 'p3';
        })
        $('.painterCircle').click(function() {
            that.panType = 'p4';
        })
        $('.painterBlock').click(function() {
            that.panType = 'p5';
        })
        $('.painterShowText').click(function() {
            that.panType = 'p6';
        })
        $('.painterDrag').click(function() {
            that.panType = 'p7';
        })
        $('.painterSave').click(function() {
            that.saveFile();
        })
        $('.painterScaleBig').click(function() {
            that.panCan.clearRect(-1000, -1000, $('#c1')[0].width * 10, $('#c1')[0].height * 10);
            that.bgCan.clearRect(-1000, -1000, $('#c0')[0].width * 10, $('#c0')[0].height * 10);
            that.scale = that.scale * 1.1;
            that.panCan.scale(1.1, 1.1);
            that.bgCan.scale(1.1, 1.1);
            // that.bgCan.drawImage(that.bgImage, that.saveX, that.saveY);
            that.bgCan.save();
            that.bgCan.translate(that.getCanRotatePoint().x, that.getCanRotatePoint().y); //将画布原点移动到旋转对象的中心位置
            that.bgCan.rotate(that.rotateCount * 90 * Math.PI / 180); //旋转画布
            that.bgCan.translate(-that.getCanRotatePoint().x, -that.getCanRotatePoint().y); //将画布原点恢复到初始状态
            that.bgCan.drawImage(that.bgImage, that.saveX, that.saveY);
            that.bgCan.restore();
            that.echo(that.panCan, that.dragArr);
        })
        $('.painterScaleSmall').click(function() {
            that.panCan.clearRect(-1000, -1000, $('#c1')[0].width * 10, $('#c1')[0].height * 10);
            that.bgCan.clearRect(-1000, -1000, $('#c0')[0].width * 10, $('#c0')[0].height * 10);
            that.scale = that.scale * 0.9;
            that.panCan.scale(0.9, 0.9);
            that.bgCan.scale(0.9, 0.9);
            // that.bgCan.drawImage(that.bgImage, that.saveX, that.saveY);
            that.bgCan.save();
            that.bgCan.translate(that.getCanRotatePoint().x, that.getCanRotatePoint().y); //将画布原点移动到旋转对象的中心位置
            that.bgCan.rotate(that.rotateCount * 90 * Math.PI / 180); //旋转画布
            that.bgCan.translate(-that.getCanRotatePoint().x, -that.getCanRotatePoint().y); //将画布原点恢复到初始状态
            that.bgCan.drawImage(that.bgImage, that.saveX, that.saveY);
            that.bgCan.restore();
            that.echo(that.panCan, that.dragArr);
        })
        $('.painterRotate').click(function() {
            that.rotateCount++;
            /* 旋转背景 */
            that.bgCan.save();
            that.bgCan.clearRect(-1000, -1000, $('#c0')[0].width * 10, $('#c0')[0].height * 10);
            that.bgCan.translate(that.getCanRotatePoint().x, that.getCanRotatePoint().y); //将画布原点移动到旋转对象的中心位置
            that.bgCan.rotate(that.rotateCount * 90 * Math.PI / 180); //旋转画布
            that.bgCan.translate(-that.getCanRotatePoint().x, -that.getCanRotatePoint().y); //将画布原点恢复到初始状态
            that.bgCan.drawImage(that.bgImage, that.saveX, that.saveY);
            that.bgCan.restore();
            /* 旋转画板 */
            that.panCan.save();
            that.panCan.clearRect(-1000, -1000, $('#c1')[0].width * 10, $('#c1')[0].height * 10);
            that.panCan.translate(that.getCanRotatePoint().x, that.getCanRotatePoint().y); //将画布原点移动到旋转对象的中心位置
            that.panCan.rotate(90 * Math.PI / 180); //旋转画布
            that.panCan.translate(-that.getCanRotatePoint().x, -that.getCanRotatePoint().y); //将画布原点恢复到初始状态
            that.echo(that.panCan, that.dragArr, true);
            that.panCan.restore();
            that.panCan.clearRect(-1000, -1000, $('#c1')[0].width * 10, $('#c1')[0].height * 10);
            that.echo(that.panCan, that.dragArr);
        })

        $('.painterBack').click(function() {
            that.panCan.clearRect(-1000, -1000, $('#c1')[0].width * 10, $('#c1')[0].height * 10);
            if (that.dragArr.length <= 0) {
                return false;
            }
            that.dragArr.pop();
            that.echo(that.panCan, that.dragArr);
            $('.painterBrush').click();
        })
        $('.painterClear').click(function() {
            that.panCan.clearRect(-1000, -1000, $('#c1')[0].width * 10, $('#c1')[0].height * 10);
            that.dragArr = [];
            $('.painterBrush').addClass('painter-active').siblings().removeClass('painter-active');
            $('.painterBrush').click();
        })

        $('#c1').on('mousedown', function(e) { /* 绘制层核心事件 */
            var e = e || window.event;
            var leaderX = e.clientX;
            var leaderY = e.clientY;
            that.x1 = e.clientX - $('#c1')[0].getBoundingClientRect().left;
            that.y1 = e.clientY - $('#c1')[0].getBoundingClientRect().top;

            that.x1 = that.x1 / that.scale;
            that.y1 = that.y1 / that.scale;

            that.panCan.fillStyle = 'red';
            that.panCan.strokeStyle = "red";
            var moveFlag = true;
            if (that.panType != 'p7') {
                var locusObj = {
                    'panType': that.panType,
                    'locus': []
                }
            }

            var throttle = function(fn, interval) { /* move节流，防止记录点过多造成卡顿性能下降 */
                var __self = fn,
                    timer, firstTime = true;
                return function() {
                    var args = arguments,
                        __me = this;
                    if (firstTime) {
                        __self.apply(__me, args);
                        return firstTime = false;
                    }
                    if (timer) {
                        return false;
                    }
                    timer = setTimeout(function() {
                        clearTimeout(timer);
                        timer = null;
                        __self.apply(__me, args);
                    }, interval || 10)
                }

            }

            function getCanPoint(e) {
                return {
                    x: e.clientX - $('#c1')[0].getBoundingClientRect().left,
                    y: e.clientY - $('#c1')[0].getBoundingClientRect().top
                }
            }

            var fnObj = {
                'p0': function() { /* 基础画笔功能 */
                    var e = e || window.event;
                    that.panCan.lineCap = "round";
                    that.panCan.lineJoin = "round";
                    that.panCan.beginPath();
                    that.panCan.moveTo(getCanPoint(e).x / that.scale, getCanPoint(e).y / that.scale);
                    locusObj.locus.push([getCanPoint(e).x / that.scale, getCanPoint(e).y / that.scale]);
                    $(document).on('mousemove', throttle(function(e) {
                        if (moveFlag) {
                            var e = e || window.event;
                            that.panCan.lineTo(getCanPoint(e).x / that.scale, getCanPoint(e).y / that.scale);
                            that.panCan.stroke(); //绘制线条
                            locusObj.locus.push([getCanPoint(e).x / that.scale, getCanPoint(e).y / that.scale]);
                        }
                    }))
                },
                'p1': function() { /* 橡皮擦功能 */
                    that.panCan.strokeStyle = "rgba(250,250,250,0)";
                    $(document).on('mousemove', throttle(function(e) {
                        that.panCan.globalCompositeOperation = "destination-out";
                        that.panCan.beginPath();
                        that.panCan.arc(getCanPoint(e).x, getCanPoint(e).y, 10, 0, 2 * Math.PI);
                        that.panCan.closePath();
                        that.panCan.fill();
                        locusObj.locus.push([getCanPoint(e).x, getCanPoint(e).y]);
                        that.panCan.globalCompositeOperation = "source-over";
                    }))
                },
                'p2': function() { /* 绘制勾 */
                    that.panCan.beginPath();
                    that.panCan.moveTo(that.x1 - 15, that.y1 - 15);
                    that.panCan.lineTo(that.x1, that.y1);
                    that.panCan.lineTo(that.x1 + 30, that.y1 - 30);
                    that.panCan.stroke();
                    locusObj.locus.push([that.x1 - 15, that.y1 - 15], [that.x1, that.y1], [that.x1 + 30, that.y1 - 30]);
                },
                'p3': function() { /* 绘制叉 */
                    that.panCan.beginPath();
                    that.panCan.moveTo(that.x1 - 15, that.y1 - 15);
                    that.panCan.lineTo(that.x1 + 15, that.y1 + 15);
                    that.panCan.moveTo(that.x1 + 15, that.y1 - 15);
                    that.panCan.lineTo(that.x1 - 15, that.y1 + 15);
                    that.panCan.stroke();
                    locusObj.locus.push([that.x1 - 15, that.y1 - 15], [that.x1 + 15, that.y1 + 15], [that.x1 + 15, that.y1 - 15], [that.x1 - 15, that.y1 + 15]);
                },
                'p4': function() { /* 绘制椭圆 */
                    that.saveDrawingSurface();
                    $(document).on('mousemove', function(e) {
                        that.restoreDrawingSurface();
                        var x2 = e.clientX - $('#c1')[0].getBoundingClientRect().left,
                            y2 = e.clientY - $('#c1')[0].getBoundingClientRect().top;
                        that.panCan.beginPath();
                        that.panCan.ellipse(that.x1, that.y1, Math.abs(x2 - that.x1), Math.abs(y2 - that.y1), 0, 0, 2 * Math.PI);
                        that.panCan.stroke();
                        locusObj.locus = [that.x1, that.y1, Math.abs(x2 - that.x1), Math.abs(y2 - that.y1)];
                    })
                },
                'p5': function() { /* 绘制矩形 */
                    that.saveDrawingSurface();
                    $(document).on('mousemove', function(e) {
                        that.restoreDrawingSurface();
                        var x2 = e.clientX - $('#c1')[0].getBoundingClientRect().left,
                            y2 = e.clientY - $('#c1')[0].getBoundingClientRect().top;
                        that.panCan.beginPath();
                        that.panCan.rect(that.x1, that.y1, (x2 - that.x1), (y2 - that.y1));
                        that.panCan.stroke();
                        locusObj.locus = [that.x1, that.y1, (x2 - that.x1), (y2 - that.y1)];
                    })
                },
                'p6': function() { /* 显示文字框 */
                    if ($('#painterText').is(':hidden')) {
                        $('#painterText').css({
                            'left': that.x1,
                            'top': that.y1 + 45
                        });
                        $('#painterText').show();
                    } else {
                        $('#painterText').hide();
                    }
                },
                'p7': function() {
                    $(document).on('mousemove', function(e) {
                        that.panCan.clearRect(-1000, -1000, $('#c1')[0].width * 10, $('#c1')[0].height * 10);
                        that.bgCan.clearRect(-1000, -1000, $('#c0')[0].width * 10, $('#c0')[0].height * 10);
                        var targetX = e.clientX - leaderX;
                        var targetY = e.clientY - leaderY;
                        that.dragX = targetX;
                        that.dragY = targetY;
                        that.saveX += targetX;
                        that.saveY += targetY;
                        leaderX = e.clientX;
                        leaderY = e.clientY;
                        that.bgCan.save();
                        that.bgCan.translate(that.getCanRotatePoint().x, that.getCanRotatePoint().y); //将画布原点移动到旋转对象的中心位置
                        that.bgCan.rotate(that.rotateCount * 90 * Math.PI / 180); //旋转画布
                        that.bgCan.translate(-that.getCanRotatePoint().x, -that.getCanRotatePoint().y); //将画布原点恢复到初始状态
                        that.bgCan.drawImage(that.bgImage, that.saveX, that.saveY);
                        that.bgCan.restore();
                        that.echo(that.panCan, that.dragArr);
                    })
                }
            }

            fnObj[that.panType]();
            $('#c1').off('mouseup')
            $('#c1').on('mouseup', function() { /* 解除事件绑定 */
                moveFlag = false;
                that.panCan.closePath();
                $(document).off('mousemove');
                $(document).off('mouseup');
                if (that.panType == 'p6' || that.panType == 'p7') { return false }
                that.dragArr.push(locusObj);
            });
        })

        $('#painterText').blur(function() { /* 绘制文字 */
            var text = $('#painterText').val();
            $('#painterText').val('');
            $('#painterText').hide();
            that.panCan.font = "14px bold 黑体";
            that.panCan.fillStyle = "red";
            that.panCan.textAlign = "left";
            that.panCan.textBaseline = "top";
            that.panCan.fillText(text, parseInt($('#painterText').css('left')), parseInt($('#painterText').css('top')) - $('#painterBar').height());
            that.dragArr.push({
                'panType': that.panType,
                'locus': [parseInt($('#painterText').css('left')), parseInt($('#painterText').css('top')) - $('#painterBar').height()],
                'text': text
            });
        })
    }

    Painter.prototype.echo = function(ctxObj, arrData, rotateFlag) {
        var that = this;
        var echoFn = {
            'p0': function(data) {
                data = data.locus;
                ctxObj.lineCap = "round";
                ctxObj.lineJoin = "round";
                ctxObj.beginPath();
                ctxObj.moveTo(data[0][0] + that.dragX, data[0][1] + that.dragY);
                data[0][0] += that.dragX;
                data[0][1] += that.dragY;
                if (rotateFlag) {
                    data[0] = that.getEndPointByRotate(data[0], [that.getCanRotatePoint().x, that.getCanRotatePoint().y], 90);
                }
                for (var i = 1; i < data.length; i++) {
                    ctxObj.lineTo(data[i][0] + that.dragX, data[i][1] + that.dragY);
                    data[i][0] += that.dragX;
                    data[i][1] += that.dragY;
                    if (rotateFlag) {
                        data[i] = that.getEndPointByRotate(data[i], [that.getCanRotatePoint().x, that.getCanRotatePoint().y], 90);
                    }
                    ctxObj.stroke(); //绘制线条
                }
                ctxObj.closePath();
            },
            'p1': function(data) {
                data = data.locus;
                for (var i = 0; i < data.length; i++) {
                    ctxObj.globalCompositeOperation = "destination-out";
                    ctxObj.beginPath();
                    ctxObj.strokeStyle = "rgba(250,250,250,0)";
                    ctxObj.arc(data[i][0] + that.dragX, data[i][1] + that.dragY, 10, 0, 2 * Math.PI);
                    ctxObj.closePath();
                    ctxObj.fill();
                    ctxObj.globalCompositeOperation = "source-over";
                    data[i][0] += that.dragX;
                    data[i][1] += that.dragY;
                    if (rotateFlag) {
                        data[i] = that.getEndPointByRotate(data[i], [that.getCanRotatePoint().x, that.getCanRotatePoint().y], 90);
                    }
                }
            },
            'p2': function(data) {
                data = data.locus;
                ctxObj.beginPath();
                ctxObj.moveTo(data[0][0], data[0][1]);
                ctxObj.lineTo(data[1][0], data[1][1]);
                ctxObj.lineTo(data[2][0], data[2][1]);
                ctxObj.stroke();

                for (var i = 0; i < data.length; i++) {
                    data[i][0] += that.dragX;
                    data[i][1] += that.dragY;
                    if (rotateFlag) {
                        data[i] = that.getEndPointByRotate(data[i], [that.getCanRotatePoint().x, that.getCanRotatePoint().y], 90);
                    }
                }
            },
            'p3': function(data) {
                data = data.locus;
                ctxObj.beginPath();
                ctxObj.moveTo(data[0][0], data[0][1]);
                ctxObj.lineTo(data[1][0], data[1][1]);
                ctxObj.moveTo(data[2][0], data[2][1]);
                ctxObj.lineTo(data[3][0], data[3][1]);
                ctxObj.stroke();
                for (var i = 0; i < data.length; i++) {
                    data[i][0] += that.dragX;
                    data[i][1] += that.dragY;
                    if (rotateFlag) {
                        data[i] = that.getEndPointByRotate(data[i], [that.getCanRotatePoint().x, that.getCanRotatePoint().y], 90);
                    }
                }
            },
            'p4': function(data) {
                data = data.locus;
                ctxObj.beginPath();
                ctxObj.ellipse(data[0], data[1], data[2], data[3], 0, 0, 2 * Math.PI);
                ctxObj.stroke();
                data[0] += that.dragX;
                data[1] += that.dragY;
                if (rotateFlag) {
                    var temp = data[2];
                    data[2] = data[3];
                    data[3] = temp;
                    var newArr = that.getEndPointByRotate([data[0], data[1]], [that.getCanRotatePoint().x, that.getCanRotatePoint().y], 90);
                    data[0] = newArr[0];
                    data[1] = newArr[1];
                }
            },
            'p5': function(data) {
                data = data.locus;
                ctxObj.beginPath();
                ctxObj.rect(data[0], data[1], data[2], data[3]);
                ctxObj.stroke();
                data[0] += that.dragX;
                data[1] += that.dragY;
                if (rotateFlag) {
                    var temp = data[2];
                    data[2] = data[3];
                    data[3] = temp;
                    var newArr = that.getEndPointByRotate([data[0], data[1]], [that.getCanRotatePoint().x, that.getCanRotatePoint().y], 90);
                    data[0] = newArr[0];
                    data[1] = newArr[1];
                }
            },
            'p6': function(data) {
                ctxObj.font = "14px bold 黑体";
                ctxObj.fillStyle = "red";
                ctxObj.textAlign = "left";
                ctxObj.textBaseline = "top";
                ctxObj.fillText(data.text, data.locus[0], data.locus[1]);
                data.locus[0] += that.dragX;
                data.locus[1] += that.dragY;
                if (rotateFlag) {
                    data.locus = that.getEndPointByRotate(data.locus, [that.getCanRotatePoint().x, that.getCanRotatePoint().y], 90);
                }

            }
        }
        $.each(arrData, function(i, v) {
            ctxObj.fillStyle = 'red';
            ctxObj.strokeStyle = "red";
            echoFn[v.panType](v);
        })
    }


    /* 保存和恢复绘图面板 */
    Painter.prototype.saveDrawingSurface = function() {
        this.drawingSurfaceImageData = this.panCan.getImageData(0, 0, $('#c1')[0].width, $('#c1')[0].height);
    }

    Painter.prototype.restoreDrawingSurface = function() {
        this.panCan.putImageData(this.drawingSurfaceImageData, 0, 0);
    }

    Painter.prototype.saveFile = function() { /* 生成绘制层图片 */
        var ctx = $('#c2')[0].getContext('2d');
        ctx.drawImage(this.bgImage, 0, 0);
        this.echo(ctx, this.dragArr)
        var imgData = $('#c2')[0].toDataURL("image/jpeg")
        this.getBase64(imgData)
    };

    Painter.prototype.getCanRotatePoint = function() {
        var that = this;
        return {
            x: (that.rotateRange) / 2 + that.saveX,
            y: (that.rotateRange) / 2 + that.saveY
        }
    }


    /**
     * startPoint  起点坐标
     * centerPoint  旋转点坐标
     * angle 旋转角度
     */
    Painter.prototype.getEndPointByRotate = function(startPoint, centerPoint, angle) {
        angle = Math.PI / 180 * angle;
        var x = (startPoint[0] - centerPoint[0]) * Math.cos(angle) - (startPoint[1] - centerPoint[1]) * Math.sin(angle) + centerPoint[0];
        var y = (startPoint[0] - centerPoint[0]) * Math.sin(angle) + (startPoint[1] - centerPoint[1]) * Math.cos(angle) + centerPoint[1];
        return [x, y];
    }

    $.fn.extend({ /* 暴露插件 */
        setCanvas: function(options) {
            options.wrapper = this || $('body');
            new Painter(options);
        }
    });
})(jQuery);



(function($, window, undefined) { /* 监听元素大小改变事件 */
    var elems = $([]),
        jq_resize = $.resize = $.extend($.resize, {}),
        timeout_id,
        str_setTimeout = 'setTimeout',
        str_resize = 'resize',
        str_data = str_resize + '-special-event',
        str_delay = 'delay',
        str_throttle = 'throttleWindow';
    jq_resize[str_delay] = 250;
    jq_resize[str_throttle] = true;
    $.event.special[str_resize] = {
        setup: function() {
            if (!jq_resize[str_throttle] && this[str_setTimeout]) {
                return false;
            }
            var elem = $(this);
            elems = elems.add(elem);
            $.data(this, str_data, {
                w: elem.width(),
                h: elem.height()
            });
            if (elems.length === 1) {
                loopy();
            }
        },
        teardown: function() {
            if (!jq_resize[str_throttle] && this[str_setTimeout]) {
                return false;
            }
            var elem = $(this);
            elems = elems.not(elem);
            elem.removeData(str_data);
            if (!elems.length) {
                clearTimeout(timeout_id);
            }
        },
        add: function(handleObj) {
            if (!jq_resize[str_throttle] && this[str_setTimeout]) {
                return false;
            }
            var old_handler;

            function new_handler(e, w, h) {
                var elem = $(this),
                    data = $.data(this, str_data);
                data.w = w !== undefined ? w : elem.width();
                data.h = h !== undefined ? h : elem.height();
                old_handler.apply(this, arguments);
            }

            if ($.isFunction(handleObj)) {
                old_handler = handleObj;
                return new_handler;
            } else {
                old_handler = handleObj.handler;
                handleObj.handler = new_handler;
            }
        }
    };

    function loopy() {
        timeout_id = window[str_setTimeout](function() {
            elems.each(function() {
                var elem = $(this),
                    width = elem.width(),
                    height = elem.height(),
                    data = $.data(this, str_data);
                if (width !== data.w || height !== data.h) {
                    elem.trigger(str_resize, [data.w = width, data.h = height]);
                }
            });
            loopy();
        }, jq_resize[str_delay]);
    }
})(jQuery, this);